﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Spanner;

namespace SpannerWebSite
{
    internal partial class RefJS : Reference
    {
        internal static SpannerChapter TheChapter;

        static RefJS()
        {
            var sections = new List<SpannerSection> { };
            var initActs = new List<Act> { };

            Action<string, string, Html> addSection = (title, id, html) => {
                sections.Add(Section(Esc(title), id, html));
            };

            addSection("JSAct act", "JSAct", P(Code("JSAct(fmt, arg1, arg2, ...)"), " is the raw JavaScript ",
                "code derived from the format string ", Code("fmt"), " with ", Code("argN"), " ",
                "substituted for the Nth '#' appearing in the format string.  For example, ",
                Code("JSAct(\"alert(# + ' ' + #)\", \"Hello\", \"World\")"), " corresponds to the JavaScript ",
                Code("alert(\"Hello\" + ' ' + \"World\")")));

            addSection("Noop", "Noop", P(Code("Noop()"), " is the JavaScript 'no operation' action, ",
                Code("{}"), "."));

            addSection("Set", "SetVariable", P(Code("Set(x, e)"), " is the JavaScript assigning ",
                Code("e"), " to ", Code("x"), " (that is: ",
                Code("x = e"), " if ", Code("x"), " is not an observable; ",
                Code("x(e)"), " if ", Code("x"), " is an observable)."));

            addSection("While", "While", P(Code("While(cond, act)"), " denotes the JavaScript ",
                Code("while (cond) { act }"), "."));

            addSection("DoWhile", "DoWhile", P(Code("DoWhile(act, cond)"), " denotes the JavaScript ",
                Code("do { act } while(cond);"), "."));

            addSection("For", "For", P(Code("For(init, cond, inc, act)"), " denotes the JavaScript ",
                Code("for(init; cond; inc) { act }"), "."));

            addSection("Continue", "Continue", P(Code("Continue()"), " denotes the JavaScript ",
                Code("continue"), " action."));

            addSection("Break", "Break", P(Code("Break()"), " denotes the JavaScript ",
                Code("break"), " action."));

            addSection("Return", "Return", P(Code("Return()"), " denotes the JavaScript ",
                Code("return"), " action (note that actions in ", Spanner, " do not return values -- ",
                "for that you need a func)."));

            addSection("IfThen", "IfThen", P(Code("IfThen(cond, thenAct)"), " denotes the JavaScript ",
                Code("if (cond) { thenAct }"), " action."));

            addSection("IfThenElse", "IfThenElse", P(Code("IfThenElse(cond, thenAct, elseAct)"),
                " denotes the JavaScript ",
                Code("if (cond) { thenAct } else { elseAct }"), " action."));

            addSection("IfCase", "IfCase", P(
                Code("IfCase(When(cond1, act1), When(cond2, act2), ..., When(condN, actN))"), " ",
                "denotes the JavaScript ",
                Code("if (cond1) { act1 } else if (cond2) { act2 } ... else if (condN) { actN }"), "."));

            addSection("Otherwise", "Otherwise", P(Code("Otherwise(act)"), " is shorthand for ",
                Code("When(true, act)"), " and is useful for the catch-all ", Code("IfCase"), " clause."));

            addSection("Do (expr)", "DoExpr", P(Code("Do(x)"), " denotes the JavaScript ",
                Code("x"), " and is used to evaluate an expression purely for its side effect ",
                "(e.g., ", Code("Do(SetTimeout(...))"), " will set a timeout, but discard the ",
                "return value  otherwisedused for ", Code("ClearTimeout"), ")."));

            addSection("Do (acts)", "DoActs", P(Code("Do(act1, act2, ..., actN)"), " denotes the JavaScript ",
                Code("{ act1; act2; ... actN; }"), " and is used to treat a sequence of actions as a single act ",
                "(a variant of this exists taking any enumerable sequence of actions)."));

            addSection("Local (initially undefined)", "LocalUndefined", P(Code("Local(x => act)"), " ",
                "denotes the JavaScript ", Code("var x; act"), "."));

            addSection("Local (with initial value)", "LocalDefined", P(Code("Local(expr, x => act)"), " ",
                "denotes the JavaScript ", Code("var x = expr; act"), "."));

            addSection("Throw (error object)", "ThrowError", P(Code("Throw(errObj)"), " denotes the JavaScript ",
                Code("throw(errObj)"), ", where the argument is a (subclass of) ", Code("JSError"), " which ",
                "specifies a single string-valued ", Code("message"), " field."));

            addSection("Throw (error message)", "ThrowError", P(Code("Throw(errMsg)"), " denotes the JavaScript ",
                Code("throw(errMsg)"), ", where the argument is a string."));

            addSection("Try", "Try", P(Code("Try(tryAct[, catchAct: x => catchAct][, finallyAct: finallyAct])"), " ",
                "denotes the JavaScript ", Code("try { tryAct } catch(x) { catchAct } finally { finallyAct }"), ". ",
                "At least one of the catch or finally parameters must be supplied."));

            addSection("VerbatimJavaScript", "VerbatimJavaScript", P(Code("VerbatimJavaScript(...)"), " ",
                "denotes the JavaScript ", Code("..."), " exactly as provided."));

            TheChapter = CommonUI.Chapter("Reference - JavaScript", "RefJS", sections, initActs);
        }
    }
}
